package com.bank.basic.service.impl;

import com.bank.basic.service.DepositService;
import com.bank.basic.service.client.AccountService;
import com.bank.basic.util.ClientFactory;
import com.bank.basic.util.EntityFactory;
import com.bank.basic.util.MapperFactory;
import com.bank.basic.util.VoFactory;
import com.bank.common.commonUtil.AuthContextHolderUtil;
import com.bank.common.exceptionUtil.CustomedException;
import com.bank.common.resultUtil.ResultCodeEnum;
import com.bank.common.stringUtil.StringUtil;
import com.bank.model.entity.Account;
import com.bank.model.entity.Deposit;
import com.bank.model.entity.User;
import com.bank.model.enums.DepositTypeEnum;
import com.bank.model.enums.InterestRateEnum;
import com.bank.model.vo.deposit.DepositAddVo;
import com.bank.model.vo.deposit.DepositHistoryVo;
import com.bank.model.vo.deposit.DepositVo;
import com.bank.model.vo.deposit.CashDepositVo;
import com.bank.model.vo.user.UserVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.MergedAnnotationPredicates;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author Cejay1314
 * @version 1.0
 * @create 2023/3/25 23:22
 */

@Service
public class DepositServiceImpl implements DepositService {
    @Autowired
    MapperFactory mapperFactory;
    @Autowired
    EntityFactory entityFactory;
    @Autowired
    VoFactory voFactory;
    @Autowired
    ClientFactory clientFactory;

    public void cashDeposit(CashDepositVo cashDepositVo) {
        Deposit deposit = entityFactory.getDeposit(cashDepositVo);
        addDepositUtil(deposit);
    }


    public List<DepositVo> queryList(Long userId) {
        QueryWrapper<Deposit> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        List<Deposit> deposits = mapperFactory.getDepositMapper().selectList(queryWrapper);
        List<DepositVo> depositVos = new ArrayList<>();
        for (Deposit deposit : deposits) {
            depositVos.add(voFactory.getDepositVo(deposit));
        }
        return depositVos;
    }

    @Override
    public List<DepositHistoryVo> queryDepositHistoryVos() {
        List<UserVo> userVos = clientFactory.getListService().getUserVo();
        List<DepositHistoryVo> depositHistoryVos = new ArrayList<>();
        for(UserVo userVo:userVos){
            List<DepositVo> depositVos = queryList(userVo.getId());
            depositHistoryVos.addAll(voFactory.getDepositHistoryVos(userVo,depositVos));

        }
        return depositHistoryVos;
    }

    @Override
    public List<Deposit> queryAll() {
        List<Deposit> deposits = mapperFactory.getDepositMapper().selectList(null);
        return deposits;
    }

    @Override
    public List<Deposit> queryAccount(String accountId) {
        QueryWrapper<Deposit> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account_id",accountId);
        List<Deposit> deposits = mapperFactory.getDepositMapper().selectList(queryWrapper);
        return deposits;
    }

    @Override
    public List<Deposit> queryUser(Long userId) {
        List<Account> accounts = clientFactory.getAccountService().getAccounts(userId);
        List<Deposit> deposits = new ArrayList<>();
        for(Account account:accounts){
            deposits.addAll(queryAccount(account.getAccountId()));
        }
        return deposits;
    }

    @Override
    public Double getAccountMoney(String accountId) {
        Double money = new Double(0);
        List<Deposit> deposits = queryAccount(accountId);
        for(Deposit deposit:deposits){
            money+=Double.parseDouble(deposit.getMoney());
        }
        return money;
    }

    @Override
    public Double getUserMoney(Long userId) {
        List<Deposit> deposits = queryUser(userId);
        Double money = new Double(0);
        for(Deposit deposit:deposits){
            money+=Double.parseDouble(deposit.getMoney());
        }
        return money;
    }

    public void addDeposit(DepositAddVo depositAddVo, HttpServletRequest httpServletRequest) {
        long userId = AuthContextHolderUtil.getUserId(httpServletRequest);
        Deposit deposit = entityFactory.getDeposit(userId, depositAddVo);
        addDepositUtil(deposit);
    }

    @Override
    public void calculateInterestRate() {
        List<Deposit> deposits = queryAll();
        for(Deposit deposit:deposits){
            Double money = new Double(0);
            if(deposit.getType() == DepositTypeEnum.DemandDeposit.getCode()){
                money = Double.parseDouble(deposit.getMoney())*(1 + Double.parseDouble(entityFactory.getStandardsMap().get(InterestRateEnum.DemandDepositInterestRate.getMessage()).getContent()));

            }else if(deposit.getType() == DepositTypeEnum.FixedDeposit.getCode()){
                money = Double.parseDouble(deposit.getMoney())*(1 + Double.parseDouble(entityFactory.getStandardsMap().get(InterestRateEnum.FixedDepositInterestRate.getMessage()).getContent()));
            }else{

            }
            deposit.setMoney(money.toString());
            mapperFactory.getDepositMapper().updateById(deposit);
        }
    }

    @Override
    public void delDeposit(Long depositId) {
        mapperFactory.getDepositMapper().deleteById(depositId);
    }

    private void addDepositUtil(Deposit deposit) {
//        活期存款
        if (deposit.getType() == DepositTypeEnum.DemandDeposit.getCode()) {
            QueryWrapper<Deposit> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("type", deposit.getType());
            Deposit deposit1 = mapperFactory.getDepositMapper().selectOne(queryWrapper);
            if (deposit1 != null) {
                deposit.setMoney(Double.parseDouble(deposit.getMoney()) + deposit1.getMoney());
                deposit.setCreatedTime(deposit1.getCreatedTime());
            }
            if (mapperFactory.getDepositMapper().insert(deposit) < 1) {
                throw new CustomedException(ResultCodeEnum.FAIL);
            }
        } else if (deposit.getType() == DepositTypeEnum.FixedDeposit.getCode()) {
            if (mapperFactory.getDepositMapper().insert(deposit) < 1) {
                throw new CustomedException(ResultCodeEnum.FAIL);
            }
        } else {
            throw new CustomedException(ResultCodeEnum.FAIL);
        }
        Account account = clientFactory.getAccountService().getAccount(deposit.getAccountId());
        Double money = Double.parseDouble(account.getMoney()) - Double.parseDouble(deposit.getMoney());
        account.setMoney(money.toString());
        account.setUpdatedTime(deposit.getUpdatedTime());
        clientFactory.getAccountService().updataAccount(account);
    }
}
